[2020年版] JavaScriptの便利な書き方まとめ
先月、Node.jsバージョン14がリリースされたこともあり、改めて最新のJavaScriptの書き方を調べてみました。その中でも特に便利だと感じたJavaScriptの書き方や普段の開発でよく利用している記法をまとめています。
アロー関数式
アロー関数式は関数を定義するための構文です。function式よりもアロー関数式の方が記述が短いので読みやすくなります。また、function式で度々問題になるthis
が固定されるので混乱を避けることができます。メソッドでない関数はアロー関数式で定義するのがよいと思います。
function name(arg) { return 'foo'; }
const name = (arg) => { return 'foo'; };
async/await
async/await
は非同期処理の構文です。また、async
は非同期関数を定義する関数定義になります。async/await
を利用すると非同期処理を同期的に扱えるので、可読性が向上してコードが読みやすくなります。
const resolveAfter2Seconds = () => { return new Promise(resolve => { setTimeout(() => { resolve('resolved'); }, 2000); }); }; const asyncCall = async () => { const result = await resolveAfter2Seconds(); console.log(result); }; asyncCall();
Promise.all
Promise.all
は引数に指定した全てのPromiseを実行します。Promiseが1つでも失敗した場合は、その時点で処理を終了してエラーを返します。
const promise1 = Promise.resolve(3); const promise2 = 42; const promise3 = new Promise(resolve => { setTimeout(resolve, 100, 'foo'); }); Promise.all([promise1, promise2, promise3]).then(values => { console.log(values); // [3, 42, 'foo'] });
配列操作のmap
メソッドと組み合わせて使用することも多いです。
const promise = val => Promise.resolve(val); const promises = [1, 2, 3].map(val => promise(val)); Promise.all(promises).then(values => { console.log(values); // [1, 2, 3] });
Promiseで失敗が発生しても処理を継続させる場合は、Promise.all
の代わりにPromise.allSettled
を使用します。一部のブラウザでは非対応でNode.jsはバージョン12以降から対応になりますので、外部ライブラリの導入も検討することになります。
配列操作
ES5以降に使えるようになった便利な配列操作のメソッドを紹介します。配列の組み込みメソッド一覧は次のページに記載されています。
forEach
forEach
は配列の各値に対して1度だけ処理を実行します。ただ、forEach
はコールバックを持たないため、非同期関数で使用するとforEach
の処理を待たずに次の処理が実行される点に注意が必要です。
['a', 'b', 'c'].forEach(val => { console.log(val); // a, b, c });
filter
filter
は配列から条件に合う値のみを取り出して、新しい配列を作成します。
const result = ['spray', 'elite', 'destruction', 'present'].filter( word => word.length > 6, ); console.log(result); // ['destruction', 'present']
map
map
は配列の値に変更を加えて、新しい配列を作成します。
const array = [1, 4, 9, 16].map(x => x * 2); console.log(array); // [2, 8, 18, 32]
reduce
reduce
は配列を処理して、1つの値を取得します。第2引数に初期値を渡すことができます。
const val = [1, 2, 3, 4].reduce( // 10 + 1 + 2 + 3 + 4 (accumulator, currentValue) => accumulator + currentValue, 10, ); console.log(val); // 20
flat
flat
は全てのサブ配列の要素を、指定した深さで再帰的に結合した新しい配列を作成します。IEは非対応でNode.jsはバージョン11から利用可能です。
const flat = [[1, 2], [3, 4]].flat(); console.log(flat); // [1, 2, 3, 4]
以前まではreduce
とconcat
を組み合わせて実装していました。
const flat = [[1, 2], [3, 4]].reduce((acc, val) => acc.concat(val), []); console.log(flat); // [1, 2, 3, 4]
変数宣言
JavaScriptの変数宣言ではvar
,let
,const
が使えます。const
で変数を宣言した場合、変数に対して値の再代入ができなくなります。これにより、値の変更を意識する必要がなくなるので、コードが読みやすくなります。可能な限り変数宣言ではconst
を利用するのがよいと思います。
条件分岐で値を変更したい場合にlet
を使いたくなりますが、三項演算子や関数で書くとconst
で宣言することができます。
let name; if (1 === 1) { name = 'orange'; } else { name = 'apple'; } console.log(name); // orange
const name = 1 === 1 ? 'orange' : 'apple'; console.log(name); // orange
const name = (() => { if (1 === 1) { return 'orange'; } else { return 'apple'; } })(); console.log(name); // orange
テンプレート文字列
テンプレート文字列(テンプレートリテラル)は文字列を扱う構文です。バッククォートで文字列を囲み、変数を代入することもできます。
const fruit = 'りんご'; const name = `美味しい${fruit}`; console.log(name); // 美味しいりんご
ヒアドキュメントのように使うこともできます。
const text = `1行目 2行目 3行目`;
スプレッド構文
スプレッド構文は配列の中で配列を展開します。
const array = ['apple', 'orange']; const array2 = ['banana', ...array]; console.log(array2); // ['banana', 'apple', 'orange']
数を指定して配列を作成したい場合、次のような書き方もできます。
const promise = Promise.resolve('foo'); const promises = [...Array(3)].map(() => promise); Promise.all(promises).then(values => { console.log(values); // ['foo', 'foo', 'foo'] });
分割代入構文
分割代入構文は、配列やオブジェクトからプロパティを取り出して、変数に代入します。
const people = ['高橋雄大', 26, 174, 63]; const [name, age, height, weight] = people;
Null合体演算子
Null合体演算子は、左辺がnull
またはundefined
の場合に右の値を返し、それ以外の場合に左の値を返します。Node.jsではバージョン14から対応になります。
const foo = null ?? 'default string'; console.log(foo); // default string
クロージャ
クロージャは関数を作るための環境を持つ関数です。変数を関数に閉じ込めることで、変数のスコープを制限します。これにより、変数がどこからでも参照できるわけではなくなるので、変数を安全に扱うことができます。また、変数の安全性を確認するために、全てのコードを見る必要もなくなるので、コードの可読性も向上します。
const makeCounter = () => { let cnt = 1; const counter = num => { cnt += num; return cnt; }; return counter; }; const counter = makeCounter(); console.log(counter(1)); // 2
まとめ
JavaScriptは次々に新しい機能が実装されて使いやすくなってきています。Node.jsについても可能であれば最新バージョンを使用して、JavaScriptの新機能を活用していきたいと思います。
今更ですがTwitterアカウント作りました!@_takahashiyudai
他にも便利な記法がありましたら、教えていただけると嬉しいです。
参考資料
- イマドキのJavaScriptの書き方2018 - Qiita
- Node.js 14が本日リリース!V8のアップグレードにより「オプショナルチェイニング」「Null合体演算子」等が利用可能に - Qiita
- あなたが知らないJavaScriptの便利すぎるショートハンド19選 – WPJ
- 4歳娘「パパ、constしか使わないで?」 - Qiita
- 4歳娘「パパ、懐かしいJavaScript書いてるね!」 - Qiita
- 4歳娘「パパ、そんなときはクロージャが役に立つんじゃない?」 - Qiita